package com.ly.demo.thread.syn;

/**
 * @author liuyang
 * @des
 * @Version 1.0
 * @Date: 22/10/2021 09:57
 */

import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;

/***
 *   6.使用阻塞队列实现线程同步
 *
 *    LinkedBlockingQueue 类常用方法
 *     LinkedBlockingQueue() : 创建一个容量为Integer.MAX_VALUE的LinkedBlockingQueue
 *     put(E e) : 在队尾添加一个元素，如果队列满则阻塞
 *     size() : 返回队列中的元素个数
 *     take() : 移除并返回队头元素，如果队列空则阻塞
 *
 *     注：BlockingQueue<E>定义了阻塞队列的常用方法，尤其是三种添加元素的方法，我们要多加注意，当队列满时：
 *
 * 　　add()方法会抛出异常
 *
 * 　　offer()方法返回false
 *
 * 　　put()方法会阻塞
 *
 */

public class BlockingSynchronizedThread {

    /**
     * LinkBlockinQueue:
     * put(E e)方法：在队尾添加一个元素，如果队列满则阻塞；
     * size():获取队列中的元素的个数
     * take():移除并返回队头元素，如果队列空则阻塞
     */

    private LinkedBlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>();

    private final static int size = 10;

    /**
     * 定义标志：0-启动生产线程；1-启动消费进程
     */
    private int flag = 0;

    private class BlockLinkQueueThread implements Runnable {

        @Override
        public void run() {

            int newFlag = flag++;
            System.out.println("启动线程：" + newFlag);

            if (newFlag == 0) {
                // 启动生产进程
                for (int i = 0; i < size; i++) {

                    int b = new Random().nextInt(10);

                    try {
                        blockingQueue.put(b);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    System.out.println("仓库还有" + blockingQueue.size() + "个商品！");

                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }

            } else {
                // 启动消费线程

                for (int j = 0; j < size / 2; j++) {

                    try {
                        int n = blockingQueue.take();
                        System.out.println("本次消费了" + n + "号商品！");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("仓库中还有" + blockingQueue.size() + "个商品！");

                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            }
        }
    }

    public static void main(String[] args) {

        BlockingSynchronizedThread bst = new BlockingSynchronizedThread();

        BlockLinkQueueThread blqt = bst.new BlockLinkQueueThread();

        Thread thread1 = new Thread(blqt);

        Thread thread2 = new Thread(blqt);

        thread1.start();

        thread2.start();

    }

}
